﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Redis.Utils
{
    /// <summary>
    /// 可排序的集合
    /// </summary>
    public partial class RedisClient_SortedSet : RedisClient
    {
        #region 增加元素
        private bool _Add(string key, int score, byte[] member)
        {
            if (!CheckKey(key))
            {
                return false;
            }
            return redisSocket.SendDataExpectInt(member, "ZADD {0} {1} {2}\r\n", key, score, member.Length) > 0 ? true : false;
        }
        /// <summary>
        /// 增加元素到SETS序列,如果元素（member）不存在则添加成功 1，否则失败 0;
        /// </summary>
        /// <param name="key"></param>
        /// <param name="member"></param>
        /// <returns></returns>
        public bool Add(string key, int score, object member)
        {
            return _Add(key, score, Serialize(member));
        }
        #endregion 增加元素

        #region 获取数据
        byte[][] _GetList(string key, int start, int end)
        {
            if (!CheckKey(key))
            {
                return null;
            }
            return redisSocket.SendDataCommandExpectMultiBulkReply(null, "ZRange {0} {1} {2}\r\n", key, start, end);
        }
        /// <summary>
        /// 返回指定键的所有值
        /// </summary>
        /// <param name="key">键</param>
        /// <returns></returns>
        public List<object> GetList(string key)
        {
            return this.GetList(key, 0, -1);
        }
        /// <summary>
        /// 返回指定键的从指定索引开始到结尾的列表
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="start">开始索引</param>
        /// <returns></returns>
        public List<object> GetList(string key, int start)
        {
            return this.GetList(key, start, -1);
        }
        /// <summary>
        /// 返回指定键的，从指定位置到另一位置的区间的值
        /// </summary>
        /// <param name="key">键</param>
        /// <param name="start">开始索引</param>
        /// <param name="end">结束索引</param>
        /// <returns></returns>
        public List<object> GetList(string key, int start, int end)
        {
            byte[][] data = _GetList(key, start, end);
            if (data == null || data.Length == 0)
            {
                return null;
            }
            List<object> returnData = new List<object>();
            foreach (byte[] item in data)
            {
                returnData.Add(Deserialize(item));
            }
            return returnData;
        }
        /// <summary>
        /// 得到指定key的成员数量
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public int GetCount(string key)
        {
            if (!CheckKey(key))
            {
                return 0;
            }
            return redisSocket.SendDataExpectInt(null, "ZCard {0}\r\n", key);

        }

        /// <summary>
        /// 获取分数(score)在min和max之间的成员数量
        /// </summary>
        /// <param name="key"></param>
        /// <param name="min"></param>
        /// <param name="max"></param>
        /// <returns></returns>
        public int GetCount(string key, int min, int max)
        {
            if (!CheckKey(key))
            {
                return 0;
            }
            return redisSocket.SendDataExpectInt(null, "zcount {0} {1} {2}\r\n", key, min, max);
        }
        #endregion

        #region 删除集合中的元素
        bool _Remove(string key, byte[] member)
        {
            if (!CheckKey(key))
            {
                return false;
            }
            return redisSocket.SendDataExpectInt(member, "ZREM {0} {1}\r\n", key, member.Length) > 0 ? true : false;
        }
        /// <summary>
        /// 删除sortset中的指定key下的某个元素
        /// </summary>
        /// <param name="key"></param>
        /// <param name="member"></param>
        /// <returns></returns>
        public bool Remove(string key, object member)
        {
            return this._Remove(key, Serialize(member));
        }
        #endregion

        #region 对指定键指定值添加排序权重
        bool _AddScore(string key, int scorce, byte[] member)
        {
            if (!CheckKey(key))
            {
                return false;
            }
            redisSocket.SendExpectData(member, "ZINCRBY   {0}  {1}  {2}\r\n", key, scorce, member.Length);
            return true;
        }

        public bool AddScore(string key, int scorce, object member)
        {
            return this._AddScore(key, scorce, Serialize(member));
        }
        #endregion

        #region 返回指定键的指定值在集合中的排名
        int _Rank(string key, byte[] member)
        {
            if (!CheckKey(key))
            {
                return 0;
            }
            return redisSocket.SendDataExpectInt(member, "ZRANK {0} {1}\r\n", key, member.Length);
        }
        public int Rank(string key, object member)
        {
            return this._Rank(key, Serialize(member));
        }
        #endregion

        #region 交运算
        bool _ZInterStore(string des, params string[] keys)
        {
            if (keys == null)
                throw new ArgumentNullException();
            return redisSocket.SendCommand("ZINTERSTORE {0} 2  {1} \r\n", des, string.Join(" ", keys)); //tmp如果存在，就自动被覆盖 
        }

        public bool ZInterStore(string des, params string[] keys)
        {
            return _ZInterStore(des, keys);
        }
        #endregion

        #region 根据score得到结果集
        byte[][] _ZRangeByScore(string key, int min, int max)
        {
            if (!IsCache)
            {
                return null;
            }
            return redisSocket.SendDataCommandExpectMultiBulkReply(null, "Zrangebyscore  {0} {1} {2} \r\n", key, min, max);
        }

        public List<object> ZRangeByScore(string key, int min, int max)
        {
            byte[][] data = _ZRangeByScore(key, min, max);
            if (data == null || data.Length == 0)
            {
                return null;
            }
            List<object> returnData = new List<object>();
            foreach (byte[] item in data)
            {
                returnData.Add(Deserialize(item));
            }
            return returnData;
        }
        #endregion
    }
}

